package com.dongdongshop.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.dongdongshop.constant.RedisSeckill;
import com.dongdongshop.mapper.seckill.TbSeckillGoodsMapper;
import com.dongdongshop.pojo.seckill.TbSeckillGoods;
import com.dongdongshop.pojo.seckill.TbSeckillGoodsExample;
import com.dongdongshop.pojo.seckill.TbSeckillOrder;
import com.dongdongshop.service.seckill.SeckillService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Component
public class SeckillServiceImpl implements SeckillService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Resource
    private TbSeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 查询所有状态良好的秒杀商品
     */
    @Override
    public List<TbSeckillGoods> getSecKillGoods() {
        RedisSerializer redisSerializer = new StringRedisSerializer();
        redisTemplate.setValueSerializer(redisSerializer);


        List<TbSeckillGoods> seckillList = redisTemplate.boundHashOps(RedisSeckill.KEY).values();
        if(seckillList == null || seckillList.size()<=0){
            TbSeckillGoodsExample example = new TbSeckillGoodsExample();
            TbSeckillGoodsExample.Criteria criteria = example.createCriteria();
            criteria.andStatusEqualTo("1");
            criteria.andStartTimeLessThanOrEqualTo(new Date());
            criteria.andEndTimeGreaterThanOrEqualTo(new Date());
            criteria.andStockCountGreaterThan(0);
            seckillList = seckillGoodsMapper.selectByExample(example);
            seckillList.stream().forEach(x-> {

                redisTemplate.boundHashOps(RedisSeckill.KEY).put(RedisSeckill.FILED + x.getId(), x);
                Integer count = x.getStockCount();
                redisTemplate.boundValueOps(x.getId()).set(count.toString());
                //redisTemplate.boundHashOps("seckillStockCount").put(x.getId(),Long.parseLong(count.toString()));
            });
        }
        return seckillList;
    }

    /**
     * 从redis缓存中
     * 根据秒杀商品id查询秒杀商品信息
     */
    @Override
    public TbSeckillGoods findSeckillById(Long id) {

        return (TbSeckillGoods)redisTemplate.boundHashOps(RedisSeckill.KEY).get(RedisSeckill.FILED+id);
    }


    @Override
    public void submitOrder(Long seckillId, Long userId) {
        RedisSerializer redisSerializer = new StringRedisSerializer();
        redisTemplate.setValueSerializer(redisSerializer);

        //判断购买次数
        //从缓存中获取秒杀商品
        Integer stockCount = Integer.parseInt(redisTemplate.boundValueOps(seckillId).get().toString());
        //如果商品不存在 null
        if(stockCount == null){
            //抛异常告诉调用方
            throw new RuntimeException("商品不存在");
        }

        //商品库存0
        if(stockCount.intValue()<=0){
            throw new RuntimeException("商品已售罄");
        }

        //扣减库存
        Long seckillStockCount = redisTemplate.boundValueOps(seckillId).decrement();
        //同步缓存
        //如果已经是最后一件商品,-1 库存就为0
        if(seckillStockCount.intValue() == 0) {//刚刚被抢光
            //同步数据库
            TbSeckillGoods seckillGoods = (TbSeckillGoods)redisTemplate.boundHashOps(RedisSeckill.KEY).get(RedisSeckill.FILED+seckillId);
            seckillGoods.setStockCount(0);
            seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);

            //卖完删除缓存
            redisTemplate.boundHashOps(RedisSeckill.KEY).delete(RedisSeckill.FILED+seckillId);
            redisTemplate.delete(seckillId);
        }
        //保存订单,订单异步生成
        Map<String,Long> msg = new HashMap<>();
        msg.put("seckillId",seckillId);
        msg.put("userId",userId);
        rocketMQTemplate.convertAndSend("SECKILLGOODS",msg);
    }

    @Override
    public TbSeckillOrder findOrder(Long seckillId, Long userId) {
        return (TbSeckillOrder)redisTemplate.boundHashOps(RedisSeckill.KEYORDER).get(userId+"_"+seckillId);
    }


}